// ---------------------------------------------------------------------
// test.c
// ---------------------------------------------------------------------

#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <config.h>
#include <simulation.h>
#include <erreur.h>
#include <archivage.h>

static void * ThreadTestProduction();
static void * ThreadTestInterface();


int main()
{
	pthread_t threadErreur, threadArchivage, threadTestProduction, threadTestInterface;
	
	mq_unlink (BAL_versErreur);
	struct mq_attr lesAttr={0,15,sizeof(MSG_versErreur),0};
	mqd_t queue_handle_versErreur;
	queue_handle_versErreur=mq_open(BAL_versErreur,O_CREAT|O_RDWR,0777, &lesAttr);
	if (queue_handle_versErreur == -1)
	{
		perror ("[TEST] Error Opening MQ BAL_versErreur:");
	}
	
	// Vers archivage
	mq_unlink (BAL_versArchivage);
	struct mq_attr lesAttrArch={0,15,sizeof(MSG_versArchivage),0};
	mqd_t queue_handle_versArchivage;
	queue_handle_versArchivage=mq_open(BAL_versArchivage,O_CREAT|O_RDWR,0777, &lesAttrArch);
	if (queue_handle_versArchivage == -1)
	{
		perror ("[TEST] Error Opening MQ queue_handle_versArchivage:");
	}
	
	// Vers Ecriture
	mq_unlink (BAL_versEcriture);
	struct mq_attr lesAttrEcri={0,15,sizeof(MSG_versEcriture),0};
	mqd_t queue_handle_versEcriture;
	queue_handle_versEcriture=mq_open(BAL_versEcriture,O_CREAT|O_RDWR,0777, &lesAttrEcri);
	if (queue_handle_versEcriture == -1)
	{
		perror ("[TEST] Error Opening MQ queue_handle_versEcriture:");
	}
	
	
	// Vers MSG_decisionErreur
	mq_unlink (BAL_decisionErreur);
	struct mq_attr lesAttrDec={0,15,sizeof(MSG_decisionErreur),0};
	mqd_t queue_handle_decisionErreur;
	queue_handle_decisionErreur=mq_open(BAL_decisionErreur,O_CREAT|O_RDWR,0777, &lesAttrDec);
	if (queue_handle_decisionErreur == -1)
	{
		perror ("[TEST] Error Opening MQ queue_handle_decisionErreur:");
	}
	
	
	// Vers MSG_retErreur
	mq_unlink (BAL_retErreur);
	struct mq_attr lesAttrRet={0,15,sizeof(MSG_retErreur),0};
	mqd_t queue_handle_retErreur;
	queue_handle_retErreur=mq_open(BAL_retErreur,O_CREAT|O_RDWR,0777, &lesAttrRet);
	if (queue_handle_retErreur == -1)
	{
		perror ("[TEST] Error Opening MQ queue_handle_retErreur:");
	}
	
	
	pthread_create (&threadTestProduction,    NULL, &ThreadTestProduction,    NULL);
	pthread_create (&threadTestInterface,    NULL, &ThreadTestInterface,    NULL);
	pthread_create (&threadErreur, NULL, &Erreur, NULL);
	pthread_create (&threadArchivage, NULL, &Archivage, NULL);
	
	pthread_join (threadErreur,    NULL);
	pthread_join (threadArchivage,    NULL);
	pthread_join (threadTestInterface,    NULL);
	pthread_join (threadTestProduction,    NULL);
	
	mq_close(queue_handle_versErreur);
	mq_unlink(BAL_versErreur);
	mq_close(queue_handle_versArchivage);
	mq_unlink(BAL_versArchivage);
	mq_close(queue_handle_versEcriture);
	mq_unlink(BAL_versEcriture);
	mq_close(queue_handle_decisionErreur);
	mq_unlink(BAL_decisionErreur);
	return 0;
}

static void * ThreadTestProduction ()
{
	mqd_t queue_handle_versErreur, queue_handle_versArchivage, queue_handle_retErreur;
	
	
	queue_handle_versErreur =  mq_open(BAL_versErreur,O_WRONLY);
	if (queue_handle_versErreur == -1)
	{
		perror ("[TEST] Error Opening MQ BAL_versErreur:");
	}
	
	queue_handle_versArchivage =  mq_open(BAL_versArchivage,O_RDWR);
	if (queue_handle_versArchivage == -1)
	{
		perror ("[TEST] Error Opening MQ BAL_versArchivage:");
	}
	
	queue_handle_retErreur =  mq_open(BAL_retErreur,O_RDONLY);
	if (queue_handle_retErreur == -1)
	{
		perror ("[TEST] Error Opening MQ BAL_retErreur:");
	}
	
	
	
	
	
	// Lancement des tests
	printf("Debut des threadTestProduction : \n\n");
	
	int tabSource[10]={T_CONDITIONNEMENT, T_IMPRESSION, T_PALETTE, T_STOCKAGE, T_DESTOCKAGE, T_LECTURE, T_ECRITURE, T_ARCHIVAGE, T_ERREUR, T_AU};
	int tabDecision[2]={REPRISE, FIN_APPLI};
	
	int numTestSource;
	int numTestDecision;
	unsigned int nb;
	
	for(numTestSource=0; numTestSource<=20; numTestSource++)
	{
		sleep(2);
		nb=rand()%1000;
		
		if(nb<=800)
		{
			sleep(1);
			printf("\n\nTest numéro %d \n",numTestSource);
				
			
			// Envoie message CR
			printf("[TEST PROD] Envoie message archivage CR \n");
			time_t temps = time(NULL);
			MSG_versArchivage messageVersArchivage;
			messageVersArchivage.source = T_IMPRESSION;
			messageVersArchivage.message = STOCK_OK;
			messageVersArchivage.heure = temps;
			messageVersArchivage.numLot = 5;
			messageVersArchivage.cartonEnCours = 4;
			messageVersArchivage.type = ARCHIVAGE;
			
			if (0 != mq_send (queue_handle_versArchivage, (const char*) &messageVersArchivage, sizeof(MSG_versArchivage), 1))
			{
				perror ("[TEST PROD] Sending to BAL_versArchivage:");
			}
		
		}
		else
		{
			// Envoie Erreur
			MSG_versErreur messageErreurRecu;
			messageErreurRecu.source = T_IMPRESSION;
		
			sleep(1);
			printf("\n\nTest numéro %d\n",numTestSource);
				
			printf("[TEST PROD] Envoie message erreur \n");
			
			messageErreurRecu.message = ERR_IMP;
			messageErreurRecu.heure = time(NULL);
			messageErreurRecu.numLot = 5;
			messageErreurRecu.cartonEnCours = 4;
			if (0 != mq_send (queue_handle_versErreur, (const char*) &messageErreurRecu, sizeof(MSG_versErreur), 2))
			{
				perror ("[TEST PROD] Sending to BAL_versArchivage:");
			}
			
			// Attente du retour Erreur
			printf("[TEST PROD] Attente du retour Erreur \n");
			MSG_retErreur messageRetErreur;
			int bytes_read = mq_receive(queue_handle_retErreur, (char*) &messageRetErreur, sizeof(MSG_retErreur), NULL);

			if (bytes_read == -1)
			{
				perror("[TEST PROD] Failed to recieve BAL_retErreur:");
			}				
			
			
			if (messageRetErreur.reponse == FIN_APPLI)
			{
				bytes_read = mq_receive(queue_handle_retErreur, (char*) &messageRetErreur, sizeof(MSG_retErreur), NULL);
				
				if (bytes_read == -1)
				{
					perror("[TEST PROD] Failed to recieve BAL_retErreur:");
				}
				
				bytes_read = mq_receive(queue_handle_retErreur, (char*) &messageRetErreur, sizeof(MSG_retErreur), NULL);

				if (bytes_read == -1)
				{
					perror("[TEST PROD] Failed to recieve BAL_retErreur:");
				}
			}
			printf("[TEST PROD] messageRetErreur : dest %d, reponse %d\n", messageRetErreur.dest, messageRetErreur.reponse); 
		
			
		}
		
		
		
		
	}
	mq_close (queue_handle_versErreur);
	mq_close (queue_handle_versArchivage);
	mq_close (queue_handle_retErreur);
}

static void * ThreadTestInterface ()
{
	mqd_t queue_handle_versArchivage, queue_handle_versEcriture, queue_handle_decisionErreur;
	
	
	queue_handle_versArchivage =  mq_open(BAL_versArchivage,O_WRONLY);
	if (queue_handle_versArchivage == -1)
	{
		perror ("[TEST INTERFACE] Error Opening MQ BAL_versArchivage:");
	}
	
	queue_handle_versEcriture =  mq_open(BAL_versEcriture,O_RDONLY);
	if (queue_handle_versEcriture == -1)
	{
		perror ("[TEST INTERFACE] Error Opening MQ BAL_versEcriture:");
	}
	
	queue_handle_decisionErreur =  mq_open(BAL_decisionErreur,O_WRONLY);
	if (queue_handle_decisionErreur == -1)
	{
		perror ("[TEST INTERFACE] Error Opening MQ BAL_decisionErreur:");
	}

	
	// Lancement des tests
	printf("Debut des tests Interface : \n\n");
	
	
	int numTestSource;
	int prio;
	
	MSG_versArchivage messageVersArchivage;
	for(numTestSource=0; numTestSource<=20; numTestSource++)
	{
		messageVersArchivage.source = T_IMPRESSION;
		
		messageVersArchivage.message = STOCK_OK;
		
				
		// Attente du dépôt d'un message dialogue opérateur
		printf("[TEST INTERFACE] Attente Ecriture \n");
		MSG_versEcriture messageEcriture;
		int bytes_read = mq_receive(queue_handle_versEcriture, (char*) &messageEcriture, sizeof(MSG_versEcriture), &prio);

		if (bytes_read == -1)
		{
			perror("[TEST INTERFACE] Failed to recieve BAL_versEcriture:");
		}
		printf("[TEST INTERFACE] messageEcriture : type %d, Message %d, numLot %d, cartonEnCours %d, prio %d \n", messageEcriture.typeMessage, messageEcriture.message, messageEcriture.numLot, messageEcriture.cartonEnCours, prio); 
		
		
		if (prio == 2)
		{
			printf("[INTERFACE] Envoie réponse opérateur \n");
			MSG_decisionErreur messagedecisionErreur;
			messagedecisionErreur.reponse = REPRISE;
			if (0 != mq_send (queue_handle_decisionErreur, (const char*) &messagedecisionErreur, sizeof(MSG_decisionErreur), 2))
			{
				perror ("[INTERFACE] Sending to queue_handle_decisionErreur:");
			}
		}
	}
	
	// Fermeture des BàL
	mq_close (queue_handle_versArchivage);
	mq_close (queue_handle_versEcriture);
}

